#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
文件覆盖策略模块
根据 template.json 配置和文件名模式，判断文件是否应该被覆盖

匹配规则示例:
- AutoStudentController.java → prefix="Auto", suffix="Controller.java" → 覆盖
- generated-api.ts → prefix="generated", suffix="api.ts" → 覆盖
- api.ts → prefix="manual", suffix="api.ts" → 不覆盖
- StudentEntity.java → prefix="", suffix="Entity.java" → 按配置的 force_overwrite 决定
"""

import json
import re
from pathlib import Path
from typing import Dict, Optional, Tuple


class FileOverwritePolicy:
    """文件覆盖策略管理器"""

    def __init__(self, template_config_path: str):
        """
        初始化覆盖策略管理器

        Args:
            template_config_path: template.json 配置文件路径
        """
        self.template_config_path = Path(template_config_path)
        self.policy_mapping: Dict[str, bool] = {}
        self._load_policy_mapping()

    def _load_policy_mapping(self):
        """从 template.json 加载文件覆盖策略映射"""
        if not self.template_config_path.exists():
            raise FileNotFoundError(f"模板配置文件不存在: {self.template_config_path}")

        try:
            with open(self.template_config_path, 'r', encoding='utf-8') as f:
                template_config = json.load(f)
        except json.JSONDecodeError as e:
            raise ValueError(f"模板配置文件格式错误: {e}")

        self.policy_mapping = {}

        for file_config in template_config.get('files', []):
            if not file_config.get('valid', True):
                continue

            prefix = file_config.get('filename-prefix', '').strip()
            suffix = file_config.get('filename-suffix', '').strip()
            force_overwrite = file_config.get('force_overwrite', False)
            file_type = file_config.get('type', '')

            # 生成文件名模式键
            pattern_key = self._generate_pattern_key(prefix, suffix, file_type)
            if pattern_key:
                self.policy_mapping[pattern_key] = force_overwrite

    def _generate_pattern_key(self, prefix: str, suffix: str, file_type: str) -> str:
        """
        生成文件名模式键

        Args:
            prefix: 文件名前缀
            suffix: 文件名后缀
            file_type: 文件类型

        Returns:
            模式键字符串
        """
        if prefix and suffix:
            return f"{prefix}::{suffix}"
        elif suffix:
            return f"::{suffix}"
        elif prefix:
            return f"{prefix}::"
        else:
            # 使用文件类型作为备用
            return f"type::{file_type}"

    def should_overwrite(self, filename: str) -> Optional[bool]:
        """
        判断文件是否应该被覆盖

        Args:
            filename: 文件名

        Returns:
            True: 应该覆盖
            False: 不应该覆盖
            None: 无法确定，使用默认策略
        """
        # 尝试匹配各种模式
        for pattern_key, should_overwrite in self.policy_mapping.items():
            if self._match_pattern(filename, pattern_key):
                return should_overwrite

        return None

    def _match_pattern(self, filename: str, pattern_key: str) -> bool:
        """
        检查文件名是否匹配模式

        Args:
            filename: 文件名
            pattern_key: 模式键

        Returns:
            是否匹配
        """
        if '::' not in pattern_key:
            return False

        prefix, suffix = pattern_key.split('::', 1)

        # 处理类型模式
        if prefix == 'type':
            return False  # 类型模式不用于直接匹配文件名

        # 只检查已知的前缀集合
        valid_prefixes = {'Auto', 'generated', 'manual'}

        # 检查前缀（只对已知前缀进行检查）
        if prefix and prefix in valid_prefixes:
            if not filename.startswith(prefix):
                return False

        # 检查后缀
        if suffix and not filename.endswith(suffix):
            return False

        return True

    def get_overwrite_strategy(self, filename: str, default_overwrite: bool = False) -> Tuple[bool, str]:
        """
        获取文件的覆盖策略和原因

        Args:
            filename: 文件名
            default_overwrite: 默认覆盖策略

        Returns:
            (是否覆盖, 策略来源说明)
        """
        result = self.should_overwrite(filename)

        if result is not None:
            reason = "根据模板配置策略"
            return result, reason
        else:
            reason = "使用默认策略"
            return default_overwrite, reason

    def list_all_patterns(self) -> Dict[str, bool]:
        """
        列出所有文件模式和覆盖策略

        Returns:
            模式到覆盖策略的映射
        """
        return self.policy_mapping.copy()


def create_policy_manager(project_dir: str) -> FileOverwritePolicy:
    """
    创建文件覆盖策略管理器的便捷函数

    Args:
        project_dir: 项目目录路径

    Returns:
        FileOverwritePolicy 实例
    """
    template_config_path = Path(project_dir) / 'templates' / 'template.json'
    return FileOverwritePolicy(str(template_config_path))


# 提供给 gen.py 使用的简化接口
def should_overwrite_file(filename: str, project_dir: str, default: bool = False) -> Tuple[bool, str]:
    """
    判断文件是否应该被覆盖的简化接口

    Args:
        filename: 文件名
        project_dir: 项目目录路径
        default: 默认覆盖策略

    Returns:
        (是否覆盖, 策略来源说明)
    """
    try:
        policy_manager = create_policy_manager(project_dir)
        return policy_manager.get_overwrite_strategy(filename, default)
    except Exception:
        # 出错时使用默认策略
        return default, "配置加载失败，使用默认策略"